<?php

use \GatewayWorker\Lib\Gateway;
use \Workerman\Lib\Timer;
use app\common\controller\Api;
use app\common\model\Property;
use think\Db;

/**
 * @auther jack<376927050@qq.com>
 * 用户相关数据提供
 */
class User
{
    public $error;
    protected static $db;
    protected static $redis;
    protected static $userinfo;

    public function __construct($token, $redis = null, $db = null)
    {
        self::$db = $db;
        self::$redis = $redis;
        self::$userinfo = $this->getUserInfoByToken($token);
    }

    /**
     * 获取用户信息
     */
    public function getUserInfo()
    {
        return self::$userinfo;
    }

    /**
     * 获取用户信息
     */
    protected function getUserInfoByToken($token)
    {
        // 参考fastadmin token生成机制
        $userToken = hash_hmac('ripemd160', $token, 'QgsxvNyOX9n3piVeC1rUKf5dShATqEIG');
        // echo $userToken;
        $data = self::$db->select('*')
            ->from('sx_user_token')
            ->where("token= '{$userToken}'")
            ->row();
        if (!$data) {
            $this->error = '无效的用户token';
            return false;
        }
        
        $uid = $data['user_id'];
        $user = self::$db->select('*')
            ->from('sx_user')
            ->where("id= '{$uid}'")
            ->row();
        if( !$user ) {
            $this->error = '无效的用户token';
            return false;
        }
        // 缓存用户状态 用作账户冻结检测
        $redisKey = "uid:{$uid}:status";
        self::$redis->set($redisKey,$user['status']);
        self::$redis->expire($redisKey, 3600);
        return $user;
    }

    /**
     * 获取用户某个股票的持仓
     */
    protected function getUserShareStrategyByCode($uid,$allNo)
    {
        $list = $this->getUserShareStrategy($uid);
        $result = [];
        foreach($list as $item){
            if( $item['all_no'] == $allNo ){
                $result[] = $item;
            }
        }
        return $result;
    }

    /**
     * 获取用户持仓列表
     */
    protected function getUserShareStrategy($uid, $status = 1, $expire = 600)
    {
        $redisKey = "stock_share_strategy:uid_$uid";

        if (self::$redis->exists($redisKey) == false) {
            $list = self::$db->select('*')
                ->from('sx_share_strategy')
                ->where("user_id= '{$uid}' and status='{$status}'")
                ->query();
            if (!$list) {
                return [];
            }
            self::$redis->set($redisKey, json_encode($list));
            self::$redis->expire($redisKey, $expire);
            return $list;
        }
        $value = self::$redis->get($redisKey);
        return json_decode($value, true);
    }

    /**
     * 资产相关
     * 1.总资产：可用的资金 + 浮动盈亏 + 所有持仓股票的保证金和
     * 2.账户余额：充值入金+平仓所得
     * 3.总持仓市值：当前持仓的所有收益
     * 4.今日持仓市值：今日买入的持仓市值
     * 5.余额收益：
     * 6.可用资金
     * 7.持仓保证金
     * 8.累计盈亏 
     * 9.浮动盈亏
     */
    public function getAsset($allNo='')
    {
        if(isset(self::$userinfo['id']) == false){
            return '无效的token';
        }
        // 检测用户状态
        $uid = self::$userinfo['id'];
        $userStatus = self::$redis->get("uid:{$uid}:status");
        $accountFreeze = $userStatus == 'freeze';

        if( $allNo ){
            $userHoldStockList = $this->getUserShareStrategyByCode($uid,$allNo);
        }else{
            $userHoldStockList = $this->getUserShareStrategy($uid);
        }

        $todayMarketValue    = 0;
        $totalMarketValue    = 0;
        $todayFloatPL        = 0;
        $totalFloatPL        = 0;
        $totalEarnestMoney   = 0;
        $balanceIncome       = 0;
        $arrUserHoldStockListDetail = [];

        if(!empty($userHoldStockList)){
            foreach ($userHoldStockList as $key => $value) 
            {
                $tmpArr = [];
                // 成交价
                $dealPrice = bcdiv($value['total_earnest'], $value['total_lever_num'], 2) * 10;
                // 现价
                $stockListKey = 'stock:hash:pricelist';
                $stockInfo = self::$redis->hget($stockListKey, $value['all_no']);
                $arrStockInfo = explode('|', $stockInfo);
                $currPrice = $arrStockInfo[2];
                // 每股盈亏
                $singleProfitLoss = bcsub($currPrice, $dealPrice, 2);
                // 总盈亏
                $totalProfitLoss = bcmul($singleProfitLoss, $value['total_lever_num'], 2);
                // 市值
                $marketValue = bcmul($currPrice, $value['total_lever_num'], 2);
                // 当天浮动盈亏
                if (time() - $value['createtime'] <=  24 * 60 * 60) {
                    $todayFloatPL += $totalProfitLoss;
                    $todayMarketValue += $marketValue; 
                }
                // 总浮动盈亏
                $totalFloatPL += $totalProfitLoss;
                // 收益率
                $incomeRate = bcdiv($singleProfitLoss, $dealPrice, 2) . '%';
                // 总市值
                $totalMarketValue += $marketValue;
                // 总保证金
                $totalEarnestMoney += floatval($value['total_earnest']);

                $tmpArr['id']              = $value['id'];
                $tmpArr['account_freeze']  = $accountFreeze;
                $tmpArr['all_no']          = $value['all_no'];
                $tmpArr['name']            = $value['name'];
                $tmpArr['total_lever_num'] = $value['total_lever_num'];
                $tmpArr['can_use_num']     = $value['can_use_num'];
                $tmpArr['total_earnest']   = $value['total_earnest'];
                $tmpArr['status']          = $value['status'];

                $tmpArr['deal_price']      = number_format($dealPrice,2);
                $tmpArr['price']           = number_format($currPrice,2);
                $tmpArr['market_value']    = number_format($marketValue,2);
                $tmpArr['income_rate']     = $incomeRate;
                $tmpArr['single_profit_loss'] =  $singleProfitLoss;
                $tmpArr['total_profit_loss']  = $totalProfitLoss;
                $tmpArr['create_at']    = date('Y-m-d H:i:s', $value['createtime']);

                $arrUserHoldStockListDetail[$key] = $tmpArr;
            }
        }
        
        $data = [];
        // 持仓列表
        $data['list'] = $arrUserHoldStockListDetail;
        // 用户是否禁用
        $data['account_freeze'] = $accountFreeze;
        // 用户余额
        $data['account_balance'] = number_format(self::$userinfo['money'],2);
        // 余额收益
        $data['balance_income']  = number_format($balanceIncome,2);
        // 今日盈亏
        $data['today_float_PL'] = number_format($todayFloatPL,2);
        // 总盈亏
        $data['total_float_PL'] = number_format($totalFloatPL,2);
        // 累计盈亏
        $data['cumulative_PL'] = self::$userinfo['cumulative_profit_loss'];
        // 今日持仓市值
        $data['today_market_value'] = number_format($todayMarketValue,2);
        // 总持仓市值
        $data['total_market_value'] = number_format($totalMarketValue,2);
        // 总保证金
        $data['total_earnest_money'] = number_format($totalEarnestMoney,2);
        // 总资产
        $sum = [
            self::$userinfo['money'],
            $totalFloatPL,
            $data['total_earnest_money']
        ];
        $assets = array_sum(array_map('floatval',$sum));
        $data['total_assets']  = number_format($assets,2);
        // 获取资产风险状态
        $data = array_merge(
            $data,
            $this->getAssetRiskStatus(self::$userinfo['money'],$data['total_earnest_money'])
        );

        return $data;
    }


    /**
     * 获取资产风险状态
     * 可用资金与保证金之和跟保证金的比例
     *（30%以下低风险，30-60%中风险，60%以上高风险）
     */
    protected function getAssetRiskStatus($money,$earnest)
    {
        $denominator = @bcadd($money,$earnest);
        $percentage = @bcdiv($earnest,$denominator,2) * 100;
        if( $percentage < 30 ){
            $status = '低风险';
        }else if( $percentage >= 30 && $percentage <= 60 ){
            $status = '中风险';
        }else{
            $status = '高风险';
        }
        return [
            'asset_risk_value'  => $percentage . '%',
            'asset_risk_status' => $status
        ];
    }

    /**
     * 获取首页资产信息
     */
    public function getIndexAssets()
    {
        $data = $this->getAsset();
        return [
            'total_assets'       => $data['total_assets'],
            'total_market_value' => $data['total_market_value']
        ];
    }

    /**
     * 持仓统计
     * today_floatPL 今日浮动盈亏
     * holdMarketValue 总持仓市值
     * floatPL  浮动盈亏
     */
    public function positionStatistics()
    {
        $data = $this->getAsset();
        $inStr = "'stock_lever_multiple','stock_cordon','closing_position_line'";
        $configList = self::$db->select('*')
                ->from('sx_config')
                ->where("`group`= 'stock' and `name` in ($inStr)")
                ->query();
                    
        $lever = 10;
        $cordon = 0.5;
        $closePositionLine = 0.8;

        if( $configList ){
            foreach( $configList as $conf){
                if( $conf['name'] == 'stock_lever_multiple' ){
                    $lever = $conf['value'];
                }else if($conf['name'] == 'stock_lever_multiple'){
                    $cordon = $conf['value'];
                }else if($conf['name'] == 'closing_position_line'){
                    $closePositionLine = $conf['value'];
                }
            }
        }

        return [
            'today_floatPL'      => $data['today_float_PL'],     // 今日浮动盈亏
            'holdMarketValue'    => $data['total_market_value'],  // 总持仓市值
            'total_floatPL'      => $data['total_float_PL'],     // 浮动盈亏
            'lever'              => $lever,                   // 杠杆
            'cordon'             => ($cordon * 100) . '%',    // 警戒线
            'closePositionLine'  => ($closePositionLine * 100) . '%'     // 平仓线
        ];
    }

     /**
     * 获取前台展示的用户持仓 详细信息
     * 成交价：新建、补仓价格的平均数
     * 现价：实时价
     * 收益率：（现价-成交价）/ 成交价
     * 总盈亏：（现价-成交价）*总数
     * 市值：总股数 * 现价
     */
    public function getUserHoldStockDetails($allNo = '')
    {
        $data = $this->getAsset($allNo);
        return $data['list'];
    }
}
